//***************************************************************************************

//                      利用ORB算法提取特征并利用FLANN进行匹配 实现特征匹配

//***************************************************************************************

#include "ImageDecMat.hpp"

void ImageDecMat::on_matchFeatures(cv::Mat Image1,cv::Mat Image2,cv::Mat& Image3)
{
    //***************检测ORB特征点并在图像中提取物体的描述符***************8
    //定义参数
    cv::OrbFeatureDetector featureDetector;
    std::vector<cv::KeyPoint>keyPoints,keyPoints_templ;
    cv::Mat descriptors,descriptors_templ;
    
    //调用detect函数检测出特征关键点，保存在vector容器中
    featureDetector.detect(Image1, keyPoints);
    featureDetector.detect(Image2, keyPoints_templ);
    //计算描述符（特征向量）
    cv::OrbDescriptorExtractor featureExtractor;
    featureExtractor.compute(Image1, keyPoints, descriptors);
    featureExtractor.compute(Image2, keyPoints_templ, descriptors_templ);
    //匹配和测试描述符，获取两个最近邻的描述符
    cv::Mat matchIndex(descriptors.rows,2,CV_32SC1),matchDistance(descriptors.rows,2,CV_32FC1);
    //基于FLANN的描述符对象匹配
    cv::flann::Index flannIndex(descriptors_templ,cv::flann::LshIndexParams(12,20,2),cvflann::FLANN_DIST_HAMMING);
    flannIndex.knnSearch(descriptors, matchIndex, matchDistance, 2,cv::flann::SearchParams());//调用k近邻算法
    //根据劳氏算法，选出优秀的匹配
    std::vector<cv::DMatch>goodMatches;
    for(int i=0;i<matchDistance.rows;++i)
    {
        if(matchDistance.at<float>(i,0)<0.6 * matchDistance.at<float>(i,1))
        {
            cv::DMatch dmatches(i,matchIndex.at<int>(i,0),matchDistance.at<float>(i,0));
            goodMatches.push_back(dmatches);
            
        }
    }
    //绘制并显示匹配窗口
    drawMatches(Image1,keyPoints,Image2,keyPoints_templ,goodMatches,Image3);

}
